package ai.ann.image.trainer.gui;


import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Iterator;
import java.util.LinkedList;

import ai.ann.Property;
import ai.ann.image.trainer.beans.ShapeBean;

import util.essential.VariableValueGetter;

/*
 * Estudiante de Ingenier�a de Ejecuci�n en Computaci�n e Inform�tica.
 * UBB - FACE - DAI - IECI.
 * Chill�n - B�o-B�o - Chile.
 * Creado el 21-01-2005
 */

/**
 * @author Sebasti�n Alexis Moraga Garrido.
 */
public class ImageComponent extends Canvas implements MouseListener, MouseMotionListener{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	//Constants:
	private static final VariableValueGetter variableValueGetter = new VariableValueGetter(Property.CONFIGURATION_FILE_NAME);
	private final int HEIGHT_MATRIX_ANALIZER = Integer.parseInt(ImageComponent.variableValueGetter.getStringValue("taste_size"));
	private final int WIDTH_MATRIX_ANALIZER = Integer.parseInt(ImageComponent.variableValueGetter.getStringValue("taste_size"));
	private final int HEIGHT_TASTE_AREA_SIZE = Integer.parseInt(ImageComponent.variableValueGetter.getStringValue("taste_area_size"));
	private final int WIDTH_TASTE_AREA_SIZE = Integer.parseInt(ImageComponent.variableValueGetter.getStringValue("taste_area_size"));
	// Atributos:
	private Image image;
	private LinkedList shapeList,listeners;
	private ShapeBean areaPointer;
	private int widthScale, heightScale;

	// Constructor:
	public ImageComponent(Image image, int width, int height) {
		this.image = image;
		this.init(width, height);
	}

	public ImageComponent(int width, int height) {
		this.image = null;
		this.init(width, height);
	}

	// Métodos:
	private void init(int width, int height){
		this.areaPointer = null;
		this.setSize(width, height);
		this.widthScale = 1;
		this.heightScale = 1;
		this.listeners = new LinkedList();
		this.shapeList = new LinkedList();
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		this.repaint();
	}
	
	public void setImage(Image image) {
		this.image = image;
		this.shapeList = new LinkedList();
		this.paint(this.getGraphics());
		//this.repaint();
	}

	public BufferedImage getBufferedImage() {
		BufferedImage tmp = new BufferedImage(this.getWidth(),
				this.getHeight(), BufferedImage.TYPE_INT_RGB);
		tmp.getGraphics().drawImage(this.image, 0, 0, this);
		return tmp;
	}

	public void paint(Graphics g) {
		g.clearRect(0, 0, this.getWidth(), this.getHeight());
		this.draw(g);
	}
	public void update(Graphics g) {
		//g.clearRect(0, 0, this.getWidth(), this.getHeight());
		this.draw(g);
	}
	public void draw(Graphics g) {
		//BufferedImage buff = new BufferedImage(this.getWidth(),
		//		this.getHeight(), BufferedImage.TYPE_INT_RGB);
		//Graphics2D g2D = (Graphics2D)buff.getGraphics();
		Graphics2D g2D = (Graphics2D) g;
		this.setBackground(Color.BLACK);
		g2D.scale(this.widthScale, this.heightScale);
		g2D.drawImage(this.image, 0, 0, this);
		if(this.shapeList != null){
			ShapeBean tmp;
			for(Iterator i=this.shapeList.iterator();i.hasNext();){
				tmp = ((ShapeBean)i.next());
				g2D.setColor(tmp.getRepresentativeColor());
				g2D.draw(tmp.getShape());
			}
		}
		if(this.areaPointer!=null){
			g2D.setColor(this.areaPointer.getRepresentativeColor());
			g2D.draw(this.areaPointer.getShape());
		}
		//g.drawImage(buff, 0, 0, null);
	}

	public int getPixel(int x, int y) {
		BufferedImage tmp = new BufferedImage(this.getWidth(),
				this.getHeight(), BufferedImage.TYPE_INT_RGB);
		tmp.getGraphics().drawImage(this.image, 0, 0, this);
		return tmp.getRGB(x, y);
	}

	public void setPixel(int x, int y, int rgb) {
		BufferedImage tmp = new BufferedImage(this.getWidth(),
				this.getHeight(), BufferedImage.TYPE_INT_RGB);
		tmp.getGraphics().drawImage(this.image, 0, 0, this);
		tmp.setRGB(x, y, rgb);
		this.image = tmp;
		this.repaint();
	}

	public void setHeightScale(int heightScale) {
		this.heightScale = heightScale;
	}

	public void setWidthScale(int widthScale) {
		this.widthScale = widthScale;
	}

	public void clearShapeList() {
		this.shapeList = new LinkedList();
		this.repaint();
	}

	public void setShapeList(LinkedList shapeList) {
		this.shapeList = shapeList;
		this.repaint();
	}
	public void loadImage(String imageFileName){
		this.setImage(Toolkit.getDefaultToolkit().getImage(imageFileName));
	}
	
	public void addListener(InformationListener listener){
		this.listeners.add(listener);
	}

	public void mouseClicked(MouseEvent arg0) {}

	public void mouseEntered(MouseEvent arg0) {}

	public void mouseExited(MouseEvent arg0) {
		this.areaPointer = null;
		this.repaint();
	}

	public void mousePressed(MouseEvent arg0) {
		int X = arg0.getX(),Y = arg0.getY();
		if(
				(this.image!=null) && 
				((X+(this.WIDTH_TASTE_AREA_SIZE/2))<this.image.getWidth(this)) &&
				((Y+(this.HEIGHT_TASTE_AREA_SIZE/2))<this.image.getHeight(this)) &&
				((X-(this.WIDTH_TASTE_AREA_SIZE/2))>=0) &&
				((Y-(this.HEIGHT_TASTE_AREA_SIZE/2))>=0)
			){
			Color[][]matrixColor=new Color[this.HEIGHT_MATRIX_ANALIZER][this.WIDTH_MATRIX_ANALIZER];
			BufferedImage bi = new BufferedImage(
					this.WIDTH_MATRIX_ANALIZER,
					this.HEIGHT_MATRIX_ANALIZER, BufferedImage.TYPE_INT_RGB);
			  bi.getGraphics().drawImage(this.getBufferedImage().getSubimage(X-(this.WIDTH_TASTE_AREA_SIZE/2),Y-(this.HEIGHT_TASTE_AREA_SIZE/2), this.WIDTH_TASTE_AREA_SIZE, this.HEIGHT_TASTE_AREA_SIZE).getScaledInstance(this.WIDTH_MATRIX_ANALIZER, this.HEIGHT_MATRIX_ANALIZER, Image.SCALE_AREA_AVERAGING), 0, 0, this); 
			
			for(int y=0;y<matrixColor.length;y++){
				for(int x=0;x<matrixColor[y].length;x++){
					matrixColor[y][x] = new Color(bi.getRGB(x,y));
				}
			}
			InformationEvent information = new InformationEvent(matrixColor,("("+X+","+Y+")"));
			ShapeBean sp = new ShapeBean(new Rectangle2D.Float(X-(this.WIDTH_TASTE_AREA_SIZE/2),Y-(this.HEIGHT_TASTE_AREA_SIZE/2),this.WIDTH_TASTE_AREA_SIZE,this.HEIGHT_TASTE_AREA_SIZE),Color.WHITE);
			this.shapeList.add(sp);
			this.repaint();
			for(Iterator i = this.listeners.iterator();i.hasNext();){
				((InformationListener)i.next()).listenToInformation(information);
			}
		}
	}

	public void mouseReleased(MouseEvent arg0) {}

	public void mouseDragged(MouseEvent arg0) {}

	public void mouseMoved(MouseEvent arg0) {
		int X = arg0.getX(),Y = arg0.getY();
		if(
				(this.image!=null) && 
				((X+(this.WIDTH_TASTE_AREA_SIZE/2))<this.image.getWidth(this)) &&
				((Y+(this.HEIGHT_TASTE_AREA_SIZE/2))<this.image.getHeight(this)) &&
				((X-(this.WIDTH_TASTE_AREA_SIZE/2))>=0) &&
				((Y-(this.HEIGHT_TASTE_AREA_SIZE/2))>=0)
			){
			this.areaPointer = new ShapeBean(new Rectangle2D.Float(X-(this.WIDTH_TASTE_AREA_SIZE/2),Y-(this.HEIGHT_TASTE_AREA_SIZE/2),this.WIDTH_TASTE_AREA_SIZE,this.HEIGHT_TASTE_AREA_SIZE),Color.WHITE);
		}else{
			this.areaPointer = null;
		}
		this.repaint();
	}
}
